package com.pfe.myrobot;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class WifiStateReceiver extends BroadcastReceiver {

	//Robot universal password
	private final String netPassword = "123456789";
	
	//WiFi states
	public final static int WIFI_CONNECTED = 1;
	public final static int WIFI_DISCONNECTED = 0;
	
	//WiFi Scan Option
	public final static int SCAN_CONNECT = 0;
	public final static int SCAN_OTHER = 1;
	
	// rssi>-55 -> Powerful signal, maximum strength.
	public static int RSSI_MAX = -55;
	// rssi<-90 -> Weak signal, minimum strength.
	public static int RSSI_MIN = -90;
	// rssi a max-min difference
	public static int RSSI_DIFF = RSSI_MAX - RSSI_MIN;
	// rssi step for 3,4,5 power bars
	public static int RSSI_STEP_3 = RSSI_DIFF /2;
	public static int RSSI_STEP_4 = RSSI_DIFF / 3;
	public static int RSSI_STEP_5 = RSSI_DIFF / 4;
	
	//Shared Preferences
	private SharedPreferences configuration;
	
	//WiFi Management
	private WifiManager wifiManager;
	private WifiConfiguration wifiConfig;
	private List<ScanResult> scanResults, robotList;
	
	//Dialog Interface
	private AlertDialog searchRobot, selectRobot, connectRobot;
	private AlertDialog.Builder searchBuilder, selectBuilder, connectBuilder;	
	private LayoutInflater inflater;
	private View searchView, connectView;
	private TextView stateText;
	private ImageView searchProg, connectProg;
	private Animation animRotate;
	
	//Current Activity
	private Activity activity;
	
	//New VS game parameters
	private NewGameParameters newGame;	
	
	private String defaultRobot;
	private boolean skipChoice = false;
	private boolean favoriteFound = false;
	private boolean changingRobot = false;
	private int scanOption = SCAN_CONNECT;
	
	//Interfaces
	private OnWifiPowerListener powerListener;
	private OnWifiStateListener stateListener;
	private OnGameCreatedListener gameListener;

	public WifiStateReceiver(Activity activity, WifiManager wifiManager) {
		this.activity = activity;
		this.wifiManager = wifiManager;
		animRotate = AnimationUtils.loadAnimation(activity, R.anim.animation_rotate_progress);
        animRotate.setInterpolator((new AccelerateDecelerateInterpolator()));
        animRotate.setFillAfter(true);
		if (activity instanceof OnWifiPowerListener) {
			powerListener = (OnWifiPowerListener) activity;
		}
		if (activity instanceof OnWifiStateListener) {
			stateListener = (OnWifiStateListener) activity;
		}
		if (activity instanceof OnGameCreatedListener) {
			gameListener = (OnGameCreatedListener) activity;
		}		
	}
	
	public WifiStateReceiver(Activity activity, WifiManager wifiManager, SharedPreferences configuration) {
		this.activity = activity;
		this.wifiManager = wifiManager;
		this.configuration = configuration;
		animRotate = AnimationUtils.loadAnimation(activity, R.anim.animation_rotate_progress);
        animRotate.setInterpolator((new AccelerateDecelerateInterpolator()));
        animRotate.setFillAfter(true);
		if (activity instanceof OnWifiPowerListener) {
			powerListener = (OnWifiPowerListener) activity;
		}
		if (activity instanceof OnWifiStateListener) {
			stateListener = (OnWifiStateListener) activity;
		}
		if (activity instanceof OnGameCreatedListener) {
			gameListener = (OnGameCreatedListener) activity;
		}
		skipChoice = configuration.getBoolean(StartMenuActivity.ALWAYS, false);
		if(skipChoice) {
			defaultRobot = configuration.getString(StartMenuActivity.NAME, "");
		}
	}
	
	public interface OnWifiPowerListener {
		public void  onWifiPowerChange(int power);
	}
	
	public interface OnWifiStateListener {
		public void onWifiStateChange(int state, String name);
	}
	
	public interface OnGameCreatedListener {
		public void onGameCreated(NewGameParameters newGame);
	}

	public void connectRobot() {
		skipChoice = configuration.getBoolean(StartMenuActivity.ALWAYS, false);
		if(skipChoice) {
			defaultRobot = configuration.getString(StartMenuActivity.NAME, "");
		}
		inflater = activity.getLayoutInflater();
		searchBuilder = new AlertDialog.Builder(activity);
		searchView = inflater.inflate(R.layout.alertwifi_layout, null);
		searchBuilder.setView(searchView);		
        searchProg = (ImageView) searchView.findViewById(R.id.dia_search_custom_prog);
        searchProg.startAnimation(animRotate);
		searchBuilder.setOnCancelListener(new OnCancelListener() {			
			@Override
			public void onCancel(DialogInterface dialog) {
				stateListener.onWifiStateChange(WIFI_DISCONNECTED, "");
				StartMenuActivity.DIALOG_IS_SHOWING = false;				
			}
		});
		searchRobot = searchBuilder.create();
		searchRobot.show();
		StartMenuActivity.DIALOG_IS_SHOWING = true;
		scanOption = SCAN_CONNECT;
		wifiManager.startScan();
	}
	
	public void searchOtherPlayers() {
		StartMenuActivity.DIALOG_IS_SHOWING = true;
		newGame = new NewGameParameters();
		inflater = activity.getLayoutInflater();
		searchBuilder = new AlertDialog.Builder(activity);
		searchView = inflater.inflate(R.layout.alertwifi_layout, null);
		searchBuilder.setView(searchView);		
        searchProg = (ImageView) searchView.findViewById(R.id.dia_search_custom_prog);
        searchProg.startAnimation(animRotate);
		searchBuilder.setOnCancelListener(new OnCancelListener() {			
			@Override
			public void onCancel(DialogInterface dialog) {
				StartMenuActivity.DIALOG_IS_SHOWING = false;				
			}
		});
		searchRobot = searchBuilder.create();
		searchRobot.show();		
		scanOption = SCAN_OTHER;
		wifiManager.startScan();
	}
	
	public void changeRobot() {
		changingRobot = true;
		connectRobot();
	}

	/**
	 * Called when a WiFi intent is received.
	 * Warning: On some devices, the WiFiManager SSID value can be between quotes.
	 * 	        Example: for a WiFi called MyWifi, the SSID can be MyWifi or "MyWifi"
	 */
	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();
		if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
			if(scanOption == SCAN_CONNECT) robotWifiScanResult();
			if(scanOption == SCAN_OTHER) otherRobotScanResult();
		}
		else if(WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {			
			NetworkInfo netInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
			Log.i("PassCheck", "if NETWORK_STATE_CHANGED_ACTION - " + netInfo.getState().name());			
			NetworkInfo.State currentState = netInfo.getState();				
			if(currentState.equals(NetworkInfo.State.CONNECTING)) {				
				if(connectRobot != null && connectRobot.isShowing()) {
					TextView stateText = (TextView) connectView.findViewById(R.id.dia_connect_custom_text);
					stateText.setText(R.string.dia_mes_wificonnecting);
				}
			}
			else if(currentState.equals(NetworkInfo.State.CONNECTED)) {
				WifiInfo info = wifiManager.getConnectionInfo();
				String robot = info.getSSID().split("-")[0];
				if(robot.equals("Robot") || robot.equals("\"Robot")) {
					stateListener.onWifiStateChange(WIFI_CONNECTED, info.getSSID());
					powerListener.onWifiPowerChange(info.getRssi());
				}
				if(connectRobot != null && connectRobot.isShowing()) connectRobot.cancel();					
			}
			else if(currentState.equals(NetworkInfo.State.DISCONNECTED)) {
				stateListener.onWifiStateChange(WIFI_DISCONNECTED, null);
				powerListener.onWifiPowerChange(-100);
			}
		}
		else if(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
			Log.i("PassCheck", "if WIFI_STATE_CHANGED_ACTION");
		}
		else if(WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
			Log.i("PassCheck", "if RSSI_CHANGED_ACTION");
			int rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, 0);
			powerListener.onWifiPowerChange(rssi);
		}
	}
	
	private void robotWifiScanResult() {
		scanResults = wifiManager.getScanResults();
		if (scanResults != null && searchRobot!= null && searchRobot.isShowing()) {			
			if (!scanResults.isEmpty()) {
				selectBuilder = new AlertDialog.Builder(activity);
				robotList = new ArrayList<ScanResult>();
				for (ScanResult result : scanResults) {
					String netName = result.SSID.split("-")[0];
					if (netName.equals("Robot") || netName.equals("\"Robot")) {
						robotList.add(result);
					}
				}
				if (!robotList.isEmpty()) {
					ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
							activity,
							android.R.layout.select_dialog_singlechoice);
					for (ScanResult robot : robotList) {
						arrayAdapter.add(robot.SSID);
					}
					selectBuilder.setAdapter(arrayAdapter,
							new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									ScanResult robot = robotList.get(which);
									dialog.cancel();
									changingRobot = false;
									StartMenuActivity.DIALOG_IS_SHOWING = true;
									robotWifiConnection(robot);
								}
							});
				} else {
					selectBuilder.setMessage(R.string.dia_mes_norobot);
				}
			} else {
				selectBuilder.setMessage(R.string.dia_mes_nowifi);
			}
			selectBuilder.setIcon(activity.getResources().getDrawable(R.drawable.wifi_level_4_50));
			selectBuilder.setTitle(R.string.dia_title_wifiselect);
			selectBuilder.setNeutralButton(R.string.refresh,
					new OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog,
								int which) {
							dialog.cancel();
							connectRobot();
						}
			});
			selectBuilder.setOnCancelListener(new OnCancelListener() {			
				@Override
				public void onCancel(DialogInterface dialog) {
					stateListener.onWifiStateChange(WIFI_DISCONNECTED, "");
					StartMenuActivity.DIALOG_IS_SHOWING = false;					
				}
			});
			selectRobot = selectBuilder.create();
			for(ScanResult robot : robotList) {
				if(skipChoice && !defaultRobot.isEmpty() && !changingRobot) {
					if(robot.SSID.equals(defaultRobot)) {
						robotWifiConnection(robot);
						favoriteFound = true;
					}
				}
			}			
			searchRobot.cancel();
			if(!skipChoice || !favoriteFound || changingRobot) {
				selectRobot.show();
				StartMenuActivity.DIALOG_IS_SHOWING = true;
			}
			favoriteFound = false;			
		} else if(scanResults == null){
			searchRobot.cancel();
			Toast.makeText(activity, "Search Failed", Toast.LENGTH_LONG)
					.show();
		}
	}
	
	private void otherRobotScanResult() {
		scanResults = wifiManager.getScanResults();
		if (scanResults != null && searchRobot!= null && searchRobot.isShowing()) {			
			if (!scanResults.isEmpty()) {
				selectBuilder = new AlertDialog.Builder(activity);
				robotList = new ArrayList<ScanResult>();
				for (ScanResult result : scanResults) {
					String netName = result.SSID.split("-")[0];
					if (netName.equals("Robot") || netName.equals("\"Robot")) {
						String myRobot = wifiManager.getConnectionInfo().getSSID();
						//if(!netName.equals(myRobot))
							robotList.add(result);
					}
				}
				if (!robotList.isEmpty()) {
					ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
							activity,
							android.R.layout.select_dialog_singlechoice);
					for (ScanResult robot : robotList) {
						arrayAdapter.add(robot.SSID);
					}
					selectBuilder.setAdapter(arrayAdapter,
							new OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.cancel();
									newGame.setOtherPlayer(robotList.get(which).SSID);
									gameListener.onGameCreated(newGame);
								}
							});
				} else {
					selectBuilder.setMessage(R.string.dia_mes_noopp);
				}
			} else {
				selectBuilder.setMessage(R.string.dia_mes_noopp);
			}
			selectBuilder.setIcon(activity.getResources().getDrawable(R.drawable.wifi_level_4_50));
			selectBuilder.setTitle(R.string.dia_title_oppselect);
			selectBuilder.setNeutralButton(R.string.refresh,
					new OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog,
								int which) {
							dialog.cancel();
							searchOtherPlayers();
						}
			});
			selectRobot = selectBuilder.create();
			searchRobot.cancel();
			selectRobot.show();
			StartMenuActivity.DIALOG_IS_SHOWING = true;
			
		} else if(scanResults == null){
			searchRobot.cancel();
			Toast.makeText(activity, "Search Failed", Toast.LENGTH_LONG)
					.show();
		}
	}
	
	private void robotWifiConnection(ScanResult robot) {
		StartMenuActivity.DIALOG_IS_SHOWING = true;
		wifiConfig = new WifiConfiguration();
		if(robot.SSID.startsWith("\"Robot")) wifiConfig.SSID = robot.SSID;
		else wifiConfig.SSID = "\"" + robot.SSID + "\"";
		wifiConfig.preSharedKey = "\""	+ netPassword + "\"";
		wifiManager.addNetwork(wifiConfig);
		List<WifiConfiguration> listNet = wifiManager.getConfiguredNetworks();
		for (WifiConfiguration network : listNet) {
			if (network.SSID != null && (network.SSID.equals("\""	+ robot.SSID + "\"") || network.SSID.equals(robot.SSID))) {
				wifiManager.disconnect();
				wifiManager.enableNetwork(network.networkId, true);			
				inflater = activity.getLayoutInflater();
				connectBuilder = new AlertDialog.Builder(activity);
				connectView = inflater.inflate(R.layout.connectwifi_layout, null);
				connectBuilder.setView(connectView);
				connectProg = (ImageView) connectView.findViewById(R.id.dia_connect_custom_prog);
				connectProg.startAnimation(animRotate);
				stateText = (TextView) connectView.findViewById(R.id.dia_connect_custom_text);
				stateText.setText(R.string.dia_mes_wifistart);
				connectBuilder.setOnCancelListener(new OnCancelListener() {			
					@Override
					public void onCancel(DialogInterface dialog) {
						StartMenuActivity.DIALOG_IS_SHOWING = false;						
					}
				});
				connectRobot = connectBuilder.create();											
				connectRobot.show();								
				wifiManager.reconnect();
				break;
			}
		}
	}
}
